package com.codebase.oval.annotation.impl;

import com.codebase.oval.annotation.Pojo;
import net.sf.oval.ConstraintViolation;
import net.sf.oval.Validator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
 * @author houkai
 */
@Aspect
@Component
public class OvalImpl {
	
	@Pointcut("@annotation(com.codebase.oval.annotation.Oval)")
	public void ovalPointcut() {  
		System.out.println("我是一个切入点");  
	} 
	
	
	@Before("ovalPointcut()")
    public void validate(JoinPoint joinPoint) throws IllegalAccessException {
        Validator validator = new Validator();
        Object[] args = joinPoint.getArgs();
        for (int i = 0;i < args.length;i++) {
            List<Object> objs = new ArrayList<>();
            this.getFiled(args[i], objs);
            for (Object obj : objs) {
                if (obj != null) {
                    List<ConstraintViolation> list = validator.validate(obj);
                    if (list != null && list.size() != 0) {
                        for (ConstraintViolation violation : list) {
                            throw new RuntimeException("错误码" + violation.getErrorCode() + "错误信息" + violation.getMessage());
                        }
                    }
                }
            }
        }
    }

    private void getFiled(Object obj, List<Object> objs) throws IllegalAccessException {
        List<Field> fields = new ArrayList<>();
        Class<?> clz = obj.getClass();
        while (clz != null && !clz.getName().toLowerCase().equals("java.lang.object")) {
            fields.addAll(Arrays.asList(clz.getDeclaredFields()));
            clz = clz.getSuperclass();
        }
        for (Field field : fields) {
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            field.setAccessible(true);
            objs.add(field.get(obj));
            //如果指定类型的注释存在于此元素上，则返回 true，否则返回 false。此方法主要是为了便于访问标记注释而设计的
            if (field.isAnnotationPresent(Pojo.class)) {
                getFiled(field.get(obj), objs);
            }
        }
        return;
    }
}
